/*                          UX-Framework                               
 *                                                                 
 *  iZE Co.,Ltd. Copyright 2009 All rights reserved.          
 *  This file is distributed under the terms of the GNU Lesser 
 *  General Public License, described in file LICENSE.                                     
 */

package jp.ize.ux.acts;

// {{{ imports
import jp.ize.ux.UXObject;
import jp.ize.ux.geom.UXPoint;
import jp.ize.ux.acts.Act;
import jp.ize.ux.tween.UXTween;
// }}}
// {{{ typedef Swapable
/**
 * SwapActが必要な関数、プロパティの定義です。
 */
typedef Swapable = {
	> ListStateType,
}
// }}}
// {{{ typedef SwapParameter > ActParameter
/**
 * 位置の交換を表現するクラス。
 */
typedef SwapParameter =
{
	> ActParameter,
	// {{{ var target1 : Int
	/**
	 * 交換対象のインデックス番号です。
	 */
	var target1 : Int;
	// }}}
	// {{{ var target2 : Int
	/**
	 * 交換対象のインデックス番号です。
	 */
	var target2 : Int;
	// }}}
}
// }}}
// {{{ class SwapAct extends Act
/**
 * SwapAct クラス<br>
 * 二つの子コンポーネントの位置を入れ替えます。<br>
 *
 * @author		iZE Co., Ltd.<br>
 * @version		$Id$<br>
 */
class SwapAct extends Act
{
	// {{{ public function new()
	/**
	 * コンストラクタ。
	 */
	public function new()
	{
		super();
	}
	// }}}
	// {{{ public function swap( sp:SwapParameter, ?interp:Swapable->SwapParameter ) : Swapable -> Void
	/**
	 * 子コンポーネントの位置を交換するアクションです。
	 */
	public function swap( sp:SwapParameter, ?interp:Swapable->SwapParameter ) : Swapable -> Void
	{
		var me = this;
		return function( state : Swapable ) {
			var param = sp;
			if ( interp!=null ) param = interp(state);
			var c1 = state.children[param.target1];
			var c2 = state.children[param.target2];
			var goal_x1 = c2.x;
			var goal_y1 = c2.y;
			var goal_x2 = c1.x;
			var goal_y2 = c1.y;
			state.children[param.target1] = c2;
			state.children[param.target2] = c1;
			var getter = function(obj:Swapable): {x1:Float,y1:Float,x2:Float,y2:Float} {
				return {
					// target1 init position
					x1:obj.children[param.target1].x,
					y1:obj.children[param.target1].y,
					// target2 init position
					x2:obj.children[param.target2].x,
					y2:obj.children[param.target2].y
				};
			};
			var setter = function(
							obj:Swapable,
							init:{x1:Float,y1:Float,x2:Float,y2:Float},
							end:{x1:Float,y1:Float,x2:Float,y2:Float},
							v:Float) {
				obj.children[param.target1].x = init.x1+(end.x1-init.x1)*v;
				obj.children[param.target1].y = init.y1+(end.y1-init.y1)*v;
				obj.children[param.target2].x = init.x2+(end.x2-init.x2)*v;
				obj.children[param.target2].y = init.y2+(end.y2-init.y2)*v;
			};
			var end = {
				x1:goal_x1,
				y1:goal_y1,
				x2:goal_x2,
				y2:goal_y2
			};
			var tw = new UXTween<Swapable,{x1:Float,y1:Float,x2:Float,y2:Float}>
						(state, end, getter, setter, param.time,
						param.transition);
			tw.setEndTweenHandler( function(e:Dynamic){
				if ( state.subject!=null ) {
					state.subject.notify(Act.STOP);
				}
			});
			var id = "swap";
			if ( !me.tm.objects.exists(id) ) {
				me.tm.registObject(id,state);
			}
			me.tm.addTweenChain(id,tw); 
			me.tm.start(id,false,state.target);
		};
	}
	// }}}
}
// }}}
